﻿#include "Netprocess.h"
#include <iostream>

using std::string;
using std::cout;
using std::endl;
using namespace std;  
using namespace ZThread;

Netprocess::Netprocess(SOCKET &_socket,int capacity):netsocket(_socket),databuffercapacity(capacity){
            isconnected = true;
            imagewidth = 0;
            imageheight = 0;
            recvframecount = 0;
            bufferheadindex = 0;
            bufferendindex = 0;   
            databuffer = NULL;
}    

void Netprocess::run(){
           //如果缓冲区没有满，接到一帧就将图片存到缓冲区尾部 
           while(true){
              if(!imagebufferIsfull() && connected()){
                  recvImage(netsocket);
              }
              //cout<<"缓冲区存货："<<buffercount()<<endl;
              if(imagebufferIsfull()){
                 cout<<"缓冲区已满"<<endl;
                 //如果缓冲区已满，则阻塞，直到缓冲区腾出空间 
                 while(true){
                     if(!imagebufferIsfull())break;
                     Thread::sleep(100);
                     if(!connected())break;
                 }        
              }    
              //如果网络断开且缓冲为空，则退出循环，接着线程自动销毁 
              if( (!connected()) && imagebufferIsempty()){
                  cout<<"接收循环退出"<<endl;   
                  Thread::sleep(1000);
                  break;
              }           
           } 
}    


void Netprocess::recvImage(SOCKET& socket){
           int datalen;
           char buftype;
           char bufsize[4];
           const int TYPE = 0;
           my_recv(socket,&buftype,1,0); 
           if(TYPE == buftype){
              //cout<<"开始接收图片"<<endl; 
              int datalen = 0;
              int _width = 0;
              int _height = 0;
              for(int i = 3;i >= 0;i--){  
                my_recv(socket,bufsize + i,1,0);
              }    
              memcpy(&_width,bufsize,4);
              for(int i = 3;i >= 0;i--){
                my_recv(socket,bufsize + i,1,0);     
              }    
              memcpy(&_height,bufsize,4);
              if( (0 < _width)&&(_width < 1200)&&(_height > 0)&&(_height < 1200) ){
                  imagewidth = _width;
                  imageheight = _height;   
              }else{
                  cout<<"网络接收图片尺寸异常"<<endl;   
              }    
              
              while(databuffer == NULL){
                  cout<<"缓冲未分配空间"<<endl;
                 //初始化缓冲区
                 //databuffer = (unsigned char*)malloc(databufferlen * imagewidth * imageheight * 3); 
                 databuffer = new unsigned char[databuffercapacity * imagewidth * imageheight * 3];
                 if(databuffer != NULL){
                    break;   
                 }    
                 Thread::sleep(200);
              }    
              for(int i = 3;i >= 0;i--){
                my_recv(socket,bufsize + i,1,0);     
              }
              memcpy(&datalen,bufsize,4);
              unsigned char *databuf = new unsigned char[datalen];
              //cout<<"imagewidth"<<imagewidth<<endl;
              //cout<<"imageheight:"<<imageheight<<endl;
              //cout<<"datalen: "<<datalen<<endl;
              my_recv_imagedata(socket,(char *)databuf,datalen);
              //将压缩数据解码成rgb 
              if(isconnected){
                  //将数据保存到缓冲尾部 
                  unsigned char * addr;
                  addr = databuffer + (imagewidth * imageheight * 3) * bufferendindex;
                  myyuv422_rgb(databuf,addr,imagewidth,imageheight);
                  bufferendindex = indexadd(bufferendindex);
              }    
              delete [] databuf;
            }    
}    

int Netprocess::my_recv_imagedata(SOCKET& socket,char *imagedata,int length){
    
    //每次接收数据块大小 
          int block_size = 512;    
          char buf[block_size];
          int index = 0;
          while( isconnected&&(length > 0) ){
              if(length > block_size){
                 if(-1 == my_recv(socket,buf,block_size,0))return -1;
                 length -= block_size;
                 memcpy(&imagedata[index],buf,block_size);
                 index += block_size;
              }else{
                 char buf2[length];
                 if(-1 == my_recv(socket,buf2,length,0))return -1;
                 length -= length;
                 memcpy(&imagedata[index],buf2,length);
                 index += length;    
              }        
          }    
          return 0;
}    

int Netprocess::my_recv(SOCKET& socket,char *buf,int length,int flag){
             int recv_len = 0;  
             short index  = 0;  
             while( isconnected&&(length > 0) ){  
               recv_len = recv(socket,&buf[index],length,flag);  
               if(-1 == recv_len){
                 cout<<"网络断开"<<endl;
                 isconnected = false;
                 return recv_len;
               }
               if(0 == recv_len){
                  recv0count++;
                  if(recv0count > 100000){
                     cout<<"等待超时,网络断开"<<endl; 
                     isconnected = false;
                     return recv_len;    
                  }        
               }else{
                  recv0count = 0;
               }         
               index    = index + recv_len;  
               length   = length - recv_len;  
             }  
              
             return recv_len;   
}    

unsigned char * Netprocess::getdataaddr(){
       //如果缓冲区非空，得到头部图片，吃一颗就向前移动一颗 
       unsigned char * addr = NULL;
       while(NULL == addr){ 
         if(!imagebufferIsempty()){  
            
            addr = databuffer + (imagewidth * imageheight * 3) * bufferheadindex;
            //从头部获取图片后，图片头索引前进1 
            bufferheadindex = indexadd(bufferheadindex);
            break;
         }    
         //if(!connected())break;
         cout<<"缓冲区空"<<endl;
         Thread::sleep(200);  
       }
       
       return addr;      
}    

int Netprocess::getheight(){
    return imageheight;
}    

int Netprocess::getwidth(){
    return imagewidth;   
}    

int Netprocess::buffercount(){
    int diff = bufferendindex - bufferheadindex;
    if(diff > 0){
        return (diff + 1);
    }else{
        if(diff == 0)return 0;
        diff = (-diff);
        return (databuffercapacity - (diff - 1) );     
    } 
    
}    

bool Netprocess::imagebufferIsfull(){
     bool boolvalue = false;
     if(buffercount() == databuffercapacity)boolvalue = true; 
     return boolvalue;
}

bool Netprocess::imagebufferIsempty(){
             bool boolvalue = false;
             if(buffercount() == 0)boolvalue = true;
             return boolvalue;      
}

int Netprocess::indexadd(int _index){
            _index ++;
            _index %= databuffercapacity;
            return _index;      
}

int Netprocess::indexsub(int _index){
            _index += databuffercapacity;
            _index --;
            return _index;    
}                

bool Netprocess::connected(){
   return  isconnected;  
}    

void Netprocess::myyuv422_rgb(const unsigned char * yuvdata,unsigned char * rgbdata,int width,int height){
    //先只用y值
    //平面格式
    int yindex = 0;
    for(int row = 0 ;row < height; row ++)
    for(int col = 0 ;col < width ; col ++){
        int rgbindex = (row * width + col) * 3;
        unsigned char y = yuvdata[yindex];
        yindex += 1;
        memset(rgbdata + rgbindex,y,3);
        
    }     
}    





